package dependenciesIO;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import customization.Constants;
import download.WebFunction;

public class DependentFunctions {

	WebFunction F1=null;

	/** input seeds for the first function **/
	ArrayList<String> inputsF1=null;

	/** the valid paths; those who do not return errors**/
	public HashMap<WebFunction, ArrayList<String>> functionsAndThePathsWhereTheyCanTakeValues= new HashMap<WebFunction, ArrayList<String>>(); 
	
	/** the path guide for all the calls of the first function;
	 *  contains the actual the inputs for the other functions**/
	DataGuideWithValuesForProbbing paths=null;
	
	
	public DependentFunctions (ArrayList<String> inputsF1, WebFunction F1){
		this.F1=F1;
		this.inputsF1=inputsF1;
	}
	
	public void clearAuxiliary(){
		paths=null;
	}
	
	
	
	public int initPathGuide() throws Exception{
		 int XMLdocuments=0;
		 paths=new DataGuideWithValuesForProbbing();
		 for(String callF1:inputsF1){
			    String inputF1=callF1.trim().replaceAll("\\s+","+");
			  	
			  	/** we do not execute the first call; we assume that the results is already download
			  	F1.executeCall(file);**/
			    
			    boolean valid=paths.makeparse(F1.getPathResultForCall(inputF1), inputF1);  
			    if(valid) XMLdocuments++;
			 }
		 return XMLdocuments;
		}
	
	public int getTotalNumberOfPaths(){
		if(paths==null) {
			if(Constants.debugMessages) {
				System.out.println("The path detaguide has not been initialized; I cannot give you the number of paths ");
			}
			return -1;
		}
		return paths.getNumberOfPaths();
	}
	 
	public Collection<String> getAllValuesUnderPath(String path){
		return paths.getAllValuesUnderPath(path);
	}
	
	
	public int computePathsWithValidInputsForSecondFunction(Collection<WebFunction> listF2) {
		/** get number of calls already executed **/
		int noCallsT1= WebFunction.counterCalls;
		
		paths.initIterator();
		int rounds=0;
		while(paths.hasNext() && rounds<Constants.maxRounds){
			  DataGuideWithValuesForProbbing.PairValueListOfDocuments pathValueDocuments=paths.next();
			  if(pathValueDocuments==null){
				  System.out.println("A round is finished \n\n");
				  rounds++;
				  continue;
			  }
			  System.out.println(pathValueDocuments.toString());
			  
			  String input=pathValueDocuments.value.trim().replaceAll("\\s+","+");;
			  
			  /** for every function execute calls taking as input the current value returned by the Iterators **/
			  for(WebFunction F2: listF2)
			  {
				  String file=F2.executeCall(input);
				  if(file!=null){
					  /** get the functions accepting as inputs values from this path **/
					  ArrayList<String> paths=functionsAndThePathsWhereTheyCanTakeValues.get(F2);
					  if(paths==null){
						  paths=new  ArrayList<String>();
						  functionsAndThePathsWhereTheyCanTakeValues.put(F2, paths);
					  }
					  paths.add(pathValueDocuments.path);
				  }
			  }
			
		  }
	
	
		
		int noCallsT2=WebFunction.counterCalls;
		return noCallsT2-noCallsT1;
	}
	
	public String toString(){
		StringBuffer buffer= new StringBuffer();
		buffer.append("Function  "+F1.functionName+" "+F1.site+" ");
		buffer.append(paths.getStringMessageCandidatesForMapping());
		buffer.append("\n\n");
		/*** path dependencies  **/
		/**for (DownloadCallResultsForFunction f: functionsAndThePathsWhereTheyCanTakeValues.keySet()){
			buffer.append(f.site+" \t\t "+F1.functionName+" \t\t "+f.functionName);
			PriorityQueue<String> orderedPaths=new PriorityQueue<String>(functionsAndThePathsWhereTheyCanTakeValues.get(f));
			while(!orderedPaths.isEmpty()){
				String path=orderedPaths.poll();
				buffer.append("\n\t Path="+path+"\t no. of values="+paths.getAllValuesUnderPath(path).size());
			}
			buffer.append("\n\n\n");
		}**/
		
		return buffer.toString();
	}
	
	
	
	public static void main(String[] args) throws Exception
	   {  
		/** set redirection 
		File file = new File("/Users/adi/Dropbox/ClementThesis/Nico-Data/iteration.txt");
		FileOutputStream fos = new FileOutputStream(file);
		PrintStream ps = new PrintStream(fos);
		System.setOut(ps); **/
		
		
		WebFunction F1= new WebFunction("getArtistByName", "musicbrainz", "http://musicbrainz.org/ws/2/artist/?query=", "");
		ArrayList<String> inputsF1=WebFunction.readInputsFromInputsAndEntitiesFiles(Constants.fileWithInputsAndEntities, 1);
		
		DependentFunctions fd=new DependentFunctions(inputsF1, F1);
		fd.initPathGuide();
		/**System.out.println(fd.paths.toString()); **/
		
		/** prepare the functions to be called **/
		WebFunction F2= new WebFunction("getReleasesByArtistId", "musicbrainz", "http://musicbrainz.org/ws/2/artist/", "?inc=releases");
		ArrayList<WebFunction> listF2=new ArrayList<WebFunction> ();
		listF2.add(F2);
		
		
		int calls=fd.computePathsWithValidInputsForSecondFunction(listF2);  
		System.out.println("Total number of calls"+calls);
		for(WebFunction f: fd.functionsAndThePathsWhereTheyCanTakeValues.keySet()){
			System.out.print("Function "+f.functionName+" accepts inputs coming from the paths :");
			for(String path: fd.functionsAndThePathsWhereTheyCanTakeValues.get(f)){
					System.out.print("    "+path);
			}
			System.out.println();
		}
	   }
	

}
